//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
/* request.cpp */

#include <protocol.h>
#include <aura.h>
#include <elacs.h>

/***********************************************************************
 *           send_request
 *
 * Send a request to the central.
 */
STATIC ECode send_request(Aura_ChannelId channelId, const struct central_request_info *__info)
{
    ECode ec;
    UInt32 data_count;

    ec = (ECode)AuraIpcChannel_AsyncWrite(channelId,
                            (PVoid)__info,
                            sizeof(struct central_request_info));

    if (FAILED(ec)) {
        Aura_printf("failed to send request. (ec = 0x%x).\n", ec);
        return ec;
    }

    data_count = __info->request_data_count;
    while (data_count--) {
        ec = (ECode)AuraIpcChannel_AsyncWrite(
                                channelId,
                                __info->request_data[data_count].ptr,
                                (Aura_UInt32)__info->request_data[data_count].size);

        if (FAILED(ec)) {
            Aura_printf("failed to send request iovec (count = %d, ec = 0x%x).\n",
                         data_count, ec);
            return ec;
        }
    }

    return ec;
}

/***********************************************************************
 *           read_reply
 *
 * read a reply from the central.
 */
STATIC ECode receive_reply(Aura_ChannelId channelId, struct central_request_info *__info)
{
    ECode ec;
    UInt32 data_count;

    ec = (ECode)AuraIpcChannel_Read(channelId,
                        (PVoid)__info,
                        sizeof(struct central_request_info));

    if (FAILED(ec)) {
        Aura_printf("failed to receive reply. (ec = 0x%x).\n", ec);
        return ec;
    }

    data_count = __info->reply_data_count;

    while (data_count--) {
        ec = (ECode)AuraIpcChannel_Read(
            channelId,
            __info->reply_data[data_count].ptr,
            (Aura_UInt32)__info->reply_data[data_count].size);

        if (FAILED(ec)) {
            Aura_printf("failed to receive reply iovec (count = %d, ec = 0x%x).\n",
                        data_count, ec);
            return ec;
        }
    }

    return ec;
}

EXTERN ECode central_call(Aura_ChannelId channelId, PVoid req_ptr, ECode * pResult)
{
    struct central_request_info * __info = (struct central_request_info *)req_ptr;
    ECode ec = NOERROR;

    ec = send_request(channelId, __info);
    if (FAILED(ec)) {
        return ec;
    }

    void * pLock = _Elastos_SequencedContext_Leave();

    ec = receive_reply(channelId, __info);

    _Elastos_SequencedContext_Enter(pLock);

    if (FAILED(ec)) {
        return ec;
    }

    *pResult = __info->u.reply.reply_header.error;

    return ec;
}

